using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Admin.NET.Application.AttributeInfo;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Core;
using Furion;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Admin.NET.Application.Filter;

public class LogMiddleware
{
	private readonly RequestDelegate _next;

	public LogMiddleware(RequestDelegate next)
	{
		_next = next;
	}

	/// <summary>
	/// 获取响应内容
	/// </summary>
	/// <param name="response"></param>
	/// <returns></returns>
	public async Task<string> GetResponse(HttpResponse response)
	{
		try
		{
			response.Body.Position = 0L;
			string text = await new StreamReader(response.Body).ReadToEndAsync();
			response.Body.Position = 0L;
			return text;
		}
		catch (Exception)
		{
			throw;
		}
	}

	public async Task Invoke(HttpContext context, SqlSugarRepository<OperationLog> _rep)
	{
		Stream originalResponseStream = context.Response.Body;
		using (context.Request.Body)
		{
			long? length = context.Request.ContentLength;
			string value = "";
			Endpoint endpoint = context.Features.Get<IEndpointFeature>()?.Endpoint;
			OperationLogAttribute attribute = null;
			if (endpoint != null)
			{
				attribute = endpoint.Metadata.GetMetadata<OperationLogAttribute>();
			}
			if (attribute == null)
			{
				await _next(context);
				return;
			}
			if (attribute != null && length.HasValue && length > 0)
			{
				context.Request.EnableBuffering();
				StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8);
				value = await reader.ReadToEndAsync();
				context.Request.Body.Position = 0L;
			}
			using MemoryStream ms = new MemoryStream();
			context.Response.Body = ms;
			await _next(context);
			ms.Position = 0L;
			StreamReader responseReader = new StreamReader(ms);
			string responseContent = responseReader.ReadToEnd();
			ms.Position = 0L;
			await ms.CopyToAsync(originalResponseStream);
			context.Response.Body = originalResponseStream;
			context.Response.OnCompleted(async delegate
			{
				HttpResponse response = context.Response;
				if (context.Request.Method.ToLower() != "get")
				{
					JObject resjob = JsonConvert.DeserializeObject(responseContent) as JObject;
					if (attribute != null && response != null && response.StatusCode == 200 && resjob != null && resjob["code"] != null && resjob["code"].ToString() == "200")
					{
						long orgId = 0L;
						long.TryParse(App.User?.FindFirst("OrgId")?.Value, out orgId);
						long userId = 0L;
						long.TryParse(App.User?.FindFirst("UserId")?.Value, out userId);
						OperationLog operationLog = new OperationLog
						{
							OrgId = orgId,
							OrgName = App.User?.FindFirst("OrgName")?.Value,
							RealName = App.User?.FindFirst("RealName")?.Value,
							UserId = userId,
							IsDelete = false,
							Data = value
						};
						JObject job = (JObject)JsonConvert.DeserializeObject(value);
						JToken id = job["id"];
						if (id != null)
						{
							long realId = 0L;
							long.TryParse(id.ToString(), out realId);
							operationLog.OperaId = realId;
						}
						operationLog.OperatName = attribute.Title;
						string[] columnName = attribute.Column.Split(',');
						string[] array = columnName;
						foreach (string item in array)
						{
							JToken column = job[item];
							if (column != null)
							{
								operationLog.Operat = operationLog.Operat + column.ToString() + ",";
							}
						}
						await _rep.InsertAsync(operationLog);
					}
				}
			});
		}
	}
}
